Dimensions des graphiques

Contenu

Rappel imagé des dimensions existantes dans un graphique

Quelles dimensions utiliser pour les petits multiples ?

Les dimensions des graphiques

Avec une dimension (une variable), on peut déjà faire un graphique

On peut également adapter la géométrie en fonction de ce qu’on veut montrer

On retrouve généralement, au moins, les dimensions cartésiennes (x et y)

On peut ajouter des dimensions en jouant sur d’autres variables visuelles

Il faut s’assurer que la variable corresponde à ce qu’on veut montrer

L’exemple précédent cherche à distinguer entre catégories, la variation sur la couleur ou la forme est donc appropriée

Dans le cas d’une variable quantitative (absolue), on peut faire varier la taille pour montrer la quantité


Un exemple concret

Résultats du championnat de foot de Premier League (Ang.)

20 équipes jouant 2x contre chacune des autres (380 matchs, saison en cours, 367 matchs joués)

Données issues de https://fbref.com


        Date  Time           Home HomeGoals AwayGoals            Away
1 2022-08-05 20:00 Crystal Palace         0         2         Arsenal
2 2022-08-06 12:30         Fulham         2         2       Liverpool
3 2022-08-06 15:00      Tottenham         4         1     Southampton
4 2022-08-06 15:00  Newcastle Utd         2         0 Nott'ham Forest
5 2022-08-06 15:00   Leeds United         2         1          Wolves
6 2023-05-28 16:30      Brentford        NA        NA Manchester City
        Date  Time           Home HomeGoals AwayGoals      Away
1 2022-08-05 20:00 Crystal Palace         0         2   Arsenal
2 2022-08-06 12:30         Fulham         2         2 Liverpool

On a des données :

  • numériques (buts)
  • catégorielles (équipes, heure de début)
  • temporelles (date, date + heure)

Commençons par les numériques en utilisant les buts pour en x et ceux contre en y

On peut dériver de nouvelles dimensions à partir des données à disposition

Ici, la fréquence des résultats (avec la fonction table())

table(pl_22_23$HomeGoals, pl_22_23$AwayGoals)
   
     0  1  2  3  4  5  6
  0 22 24 23  9  3  0  0
  1 44 35 21  8  6  3  1
  2 26 31 20  6  4  0  0
  3 15 17  6  5  0  0  0
  4  9  9  3  5  0  0  0
  5  1  1  2  1  0  0  0
  6  2  1  1  1  0  0  0
  7  1  0  0  0  0  0  0
  9  1  0  0  0  0  0  0

En se battant un peu avec les données, on obtient un jdd utilisable (= au format tidy)

pl_22_23 |> 
  group_by(HomeGoals, AwayGoals) |> 
  summarise(freq = n()) |> 
  head(8)
# A tibble: 8 × 3
# Groups:   HomeGoals [2]
  HomeGoals AwayGoals  freq
      <dbl>     <dbl> <int>
1         0         0    22
2         0         1    24
3         0         2    23
4         0         3     9
5         0         4     3
6         1         0    44
7         1         1    35
8         1         2    21

pl_22_23 |> 
  group_by(HomeGoals, AwayGoals) |> 
  summarise(freq = n()) |> 
ggplot() +
  geom_point(aes(HomeGoals, AwayGoals, size = freq)) +
  coord_fixed(xlim = c(0,6),
              ylim = c(0,6)) +
  labs(title = "Scores des matchs de Premier League") +
  theme(plot.title = element_text(family = "Premier League"))

On peut rajouter une dimension pour aider la lecture


Si l’équipe à dom. marque plus qu’elle n’encaisse, elle gagne

Dans le cas inverse, elle perd

Si les équipes ont un score égal, c’est un match nul

pl_22_23 |> 
  group_by(HomeGoals, AwayGoals) |> 
  summarise(freq = n()) |>
  mutate(rslt = case_when(
                  HomeGoals > AwayGoals ~ "victoire",
                  HomeGoals < AwayGoals ~ "défaite",
                  HomeGoals == AwayGoals ~ "nul"))
# A tibble: 3 × 4
  HomeGoals AwayGoals  freq rslt    
      <dbl>     <dbl> <int> <chr>   
1         0         0    22 nul     
2         1         2    21 défaite 
3         4         2     3 victoire

couleurs_rslt <- c("victoire" = "#00985f", "défaite" = "#e55e5b", "nul" = "#7b8288")

pl_22_23 |> 
  filter(! is.na(HomeGoals)) |> 
  group_by(HomeGoals, AwayGoals) |> 
  summarise(freq = n()) |>
  mutate(rslt = case_when(
                  HomeGoals > AwayGoals ~ "victoire",
                  HomeGoals < AwayGoals ~ "défaite",
                  HomeGoals == AwayGoals ~ "nul")) |> 
ggplot() +
  geom_point(aes(HomeGoals, AwayGoals, size = freq, color = rslt)) +
  coord_fixed(xlim = c(0,6),
              ylim = c(0,6)) +
  scale_color_manual(values = couleurs_rslt) +
  labs(title = "Scores des matchs de Premier League") +
  theme(plot.title = element_text(family = "Premier League"))

Derniers ajustements cosmétiques :

  • Aide à la lecture
  • Intégration de la légende des couleurs
  • Informations supplémentaires
  • Labelisation correcte
  • Attribution des sources

# Préparation des fréquences et résultats
freq_scores_rslt <- pl_22_23 |> 
  filter(! is.na(HomeGoals)) |> 
  group_by(HomeGoals, AwayGoals) |> 
  summarise(freq = n()) |>
  mutate(rslt = case_when(
                  HomeGoals > AwayGoals ~ "victoire",
                  HomeGoals < AwayGoals ~ "défaite",
                  HomeGoals == AwayGoals ~ "nul"))

# Calcul des infos supplémentaires
nb_matchs <- sum(freq_scores_rslt$freq)
nb_vict <- sum(freq_scores_rslt[freq_scores_rslt$rslt == "victoire", "freq"])
nb_def <- sum(freq_scores_rslt[freq_scores_rslt$rslt == "défaite", "freq"])
nb_nul <- sum(freq_scores_rslt[freq_scores_rslt$rslt == "nul", "freq"])

# Couleurs des rslts
couleurs_rslt <- c("victoire" = "#00985f", "défaite" = "#e55e5b", "nul" = "#7b8288")
  
freq_scores_rslt |> 
ggplot() +
  geom_segment(x = 0, y = 0, xend = 6, yend = 6, linewidth = 0.5, color = "grey85") +
  geom_point(aes(HomeGoals, AwayGoals, size = freq, color = rslt)) +
  geom_curve(aes(x = 4.55, y = 3.25, xend = 4.1, yend = 2.1),
             arrow = arrow(length = unit(0.12, "inch")), size = 0.5,
             color = "gray40", curvature = -0.2) +
  annotate("text", x = 4.55, y = 3.4, label = "3 matchs ont fini à 4-2", size = 4, color = "gray40", hjust = 0.5) +
  coord_fixed(xlim = c(0.5, 5.5),
              ylim = c(0.5, 5.5)) +
  scale_x_discrete(limits = c(0:6)) +
  scale_y_discrete(limits = c(0:6)) +
  scale_color_manual(values = couleurs_rslt) +
  scale_size_area(breaks = c(max(freq_scores_rslt$freq), 21, 10, 5)) +
  labs(title = "Scores des matchs de Premier League",
       subtitle = str_glue("Saison 22/23 - {nb_matchs} matchs: ", 
                           "<span style = 'color:#00985f;'>{nb_vict}  victoires</span> et ",
                           "<span style = 'color:#e55e5b;'>{nb_def} défaites</span> ",
                           "à domicile, ",
                           "<span style = 'color:#7b8288;'>{nb_nul} nuls</span>"),
       x = "Buts marqués à domicile",
       y = "Buts encaissés à domicile",
       size = "Matchs",
       caption = "Données FBref.com | 2 matchs non affichés (9-0, 7-0)") +
  theme_minimal() +
  theme(text = element_text(family = "Century Gothic"),
        plot.title = element_text(family = "Premier League"),
        plot.subtitle = element_markdown(),
        panel.grid.major = element_line(color = "gray95"),
        legend.position = c(0.75, 0.77),
        legend.background = element_rect(fill = alpha("white", 0.8), linetype = "blank"),
        axis.title.x = element_text(margin = margin(10, 0, 0, 0)),
        axis.title.y = element_text(margin = margin(0, 10, 0, 0)),
        plot.caption = element_text(color = "gray65", margin = margin(10,0,0,0))) +
  guides(color="none")

Toujours plus de dimensions !

Pour complexifier (et utiliser des petits multiples)

  • Comparaison avec d’autres championnats (catégoriel)
  • Distinction en fonction des saisons (années / temporel)
  • Distinction selon les équipes (catégoriel)

et…combinaisons des éléments précédents

couleurs_rslt <- c("victoire" = "#00985f", "défaite" = "#e55e5b", "nul" = "#7b8288")

leagues_22_23 <- rbind(pl_22_23, liga_22_23, seriea_22_23)

leagues_22_23 |> 
  group_by(Competition_Name, HomeGoals, AwayGoals) |> 
  summarise(freq = n()) |>
  mutate(rslt = case_when(
                  HomeGoals > AwayGoals ~ "victoire",
                  HomeGoals < AwayGoals ~ "défaite",
                  HomeGoals == AwayGoals ~ "nul")) |> 
  ggplot() +
  facet_wrap(~ Competition_Name, nrow = 1) +
  geom_point(aes(HomeGoals, AwayGoals, size = freq, color = rslt)) +
  coord_fixed(xlim = c(0.3, 5.5),
              ylim = c(0.3, 5.5)) +
  scale_x_discrete(limits = c(0:6)) +
  scale_y_discrete(limits = c(0:6)) +
  scale_color_manual(values = couleurs_rslt) +
  labs(title = "Scores des matchs de championnats européens",
       subtitle = "Saison 2022/23",
       x = "Buts marqués à domicile",
       y = "Buts encaissés à domicile") +
  theme_minimal(base_size = 15) +
  theme(legend.position = "none",
        strip.text.x = element_text(face = "bold"),
        text = element_text(family = "Century Gothic"),
        axis.title.x = element_text(margin = margin(10, 0, 0, 0)),
        axis.title.y = element_text(margin = margin(0, 10, 0, 0)),
        axis.title = element_text(size = 10),
        panel.spacing.x = unit(2, "lines"))

couleurs_rslt <- c("victoire" = "#00985f", "défaite" = "#e55e5b", "nul" = "#7b8288")

pl_20_23 <- rbind(pl_22_23, pl_21_22, pl_20_21)

pl_20_23 |> 
  group_by(Season_End_Year, HomeGoals, AwayGoals) |> 
  summarise(freq = n()) |>
  mutate(rslt = case_when(
                  HomeGoals > AwayGoals ~ "victoire",
                  HomeGoals < AwayGoals ~ "défaite",
                  HomeGoals == AwayGoals ~ "nul")) |> 
  ggplot() +
  facet_wrap(~ Season_End_Year) +
  geom_point(aes(HomeGoals, AwayGoals, size = freq, color = rslt)) +
  coord_fixed(xlim = c(0.3, 5.5),
              ylim = c(0.3, 5.5)) +
  scale_x_discrete(limits = c(0:6)) +
  scale_y_discrete(limits = c(0:6)) +
  scale_color_manual(values = couleurs_rslt) +
  labs(title = "Scores des matchs de Premier League",
       subtitle = "Saisons 2020/21 à 2022/23",
       x = "Buts marqués à domicile",
       y = "Buts encaissés à domicile") +
  theme_minimal(base_size = 15) +
  theme(legend.position = "none",
        strip.text.x = element_text(face = "bold"),
        text = element_text(family = "Century Gothic"),
        title = element_text(family = "Premier League"),
        axis.title.x = element_text(margin = margin(10, 0, 0, 0)),
        axis.title.y = element_text(margin = margin(0, 10, 0, 0)),
        panel.spacing = unit(2, "lines"))

rslt_equipes_pl <- data.frame(goal_for = numeric(), goal_against = numeric(), n = numeric(), team = numeric())

for (team in unique(pl_22_23$Home)){
  freq_rslt_team <- pl_22_23 |> 
    filter((Home == team | Away == team) & ! is.na(HomeGoals)) |> 
    select(Home, HomeGoals, Away, AwayGoals) |> 
    mutate(goal_for = if_else(Home == team, HomeGoals, AwayGoals),
           goal_against = if_else(Home == team, AwayGoals, HomeGoals)) |> 
    group_by(goal_for, goal_against) |> 
    summarise(n = n()) |> 
    mutate(team = team)
  rslt_equipes_pl <- rbind(rslt_equipes_pl, freq_rslt_team)
}

classement_pl <- fb_season_team_stats("ENG", "M", 2023, "1st", "league_table")

ordre_equipes <- classement_pl |> 
  arrange(Rk) |> 
  pull(Squad)

couleurs_rslt <- c("victoire" = "#00985f", "défaite" = "#e55e5b", "nul" = "#7b8288")

rslt_equipes_pl |>
  mutate(bp = goal_for, bc = goal_against, rslt = case_when(bp > bc ~ "victoire",
                                                            bp < bc ~ "défaite",
                                                            .default = "nul")) |>
  dplyr::filter(team %in% ordre_equipes[c(1,2,3,4,10,11,12,18,19,20)]) |>
  ggplot() +
    facet_wrap(~ factor(team, levels = ordre_equipes), nrow = 2) +
    geom_segment(x = 0, y = 0, xend = 6, yend = 6, linewidth = 0.4, color = "grey90") +
    geom_point(aes(bp, bc, size = n, color = rslt)) +
    scale_x_continuous(limits = c(0, 6), breaks = c(0:6)) +
    scale_y_continuous(limits = c(0, 6), breaks = c(0:6)) +
    scale_color_manual(values = couleurs_rslt) +
    coord_fixed(xlim = c(0, 5.8),
                ylim = c(0, 5.8), clip = "off") +
    scale_size_area(max_size = 4) +
    labs(title = "Scores d'équipes de Premier League",
         subtitle = "Équipes classées 1, 2, 3, 4, 10 | 11, 12, 18, 19, 20",
         x = "Buts marqués",
         y = "Buts encaissés",
         size = "Nombre \nde matchs") +
    theme_minimal(base_size = 15) +
    theme(panel.grid.minor = element_blank(),
          panel.grid.major = element_line(color = "gray95"),
          text = element_text(family = "Century Gothic"),
          plot.title = element_text(color = "gray35"),
          plot.subtitle = element_text(color = "gray65", size = 12),
          axis.title = element_text(size = 6),
          strip.text = element_text(size = 9, family = "Premier League", colour = "gray40"),
          axis.text = element_text(size = 6),
          axis.title.x = element_text(margin = margin(8, 0, 0, 0)),
          axis.title.y = element_text(margin = margin(0, 5, 0, 0)),
          axis.text.x = element_text(margin = margin(-4,0,0,0)),
          panel.spacing.x = unit(1.5, "lines"),
          legend.position = "none") +
    guides(color="none")

rslt_equipes_pl_20_23 <- data.frame(goal_for = numeric(), goal_against = numeric(), n = numeric(), team = numeric())

for (team in unique(pl_22_23$Home)){
  freq_rslt_team <- pl_20_23 |> 
    filter((Home == team | Away == team) & ! is.na(HomeGoals)) |> 
    select(Season_End_Year, Home, HomeGoals, Away, AwayGoals) |> 
    mutate(goal_for = if_else(Home == team, HomeGoals, AwayGoals),
           goal_against = if_else(Home == team, AwayGoals, HomeGoals)) |> 
    group_by(Season_End_Year, goal_for, goal_against) |> 
    summarise(n = n()) |> 
    mutate(team = team,
           season = Season_End_Year)
  rslt_equipes_pl_20_23 <- rbind(rslt_equipes_pl_20_23, freq_rslt_team)
}

couleurs_rslt <- c("victoire" = "#00985f", "défaite" = "#e55e5b", "nul" = "#7b8288")

rslt_equipes_pl_20_23 |>
  mutate(bp = goal_for, bc = goal_against, rslt = case_when(bp > bc ~ "victoire",
                                                            bp < bc ~ "défaite",
                                                            .default = "nul")) |>
  dplyr::filter(team %in% c("Newcastle Utd", "Brighton") & season %in% c(2021, 2022, 2023)) |>
  ggplot() +
    facet_grid(team ~ season) +
    geom_segment(x = 0, y = 0, xend = 6, yend = 6, linewidth = 0.4, color = "grey90") +
    geom_point(aes(bp, bc, size = n, color = rslt)) +
    scale_x_continuous(limits = c(0, 6), breaks = c(0:6)) +
    scale_y_continuous(limits = c(0, 6), breaks = c(0:6)) +
    scale_color_manual(values = couleurs_rslt) +
    coord_fixed(xlim = c(0, 5.8),
                ylim = c(0, 5.8), clip = "off") +
    scale_size_area(max_size = 4) +
    labs(title = "Évolution des résultats de Newcastle Utd et Brighton",
         x = "Buts marqués",
         y = "Buts encaissés",
         size = "Nombre \nde matchs") +
    theme_minimal(base_size = 15) +
    theme(panel.grid.minor = element_blank(),
          panel.grid.major = element_line(color = "gray95"),
          text = element_text(family = "Century Gothic"),
          plot.title = element_text(color = "gray25", size = 14),
          axis.title = element_text(size = 6),
          strip.text = element_text(size = 9, family = "Premier League", colour = "gray40"),
          axis.text = element_text(size = 6),
          panel.spacing = unit(1, "lines"),
          legend.position = "none") +
    guides(color="none")

Exemple d’amélioration

Avec R, il est possible d’obtenir le même résultat

On préfère des petits multiples pour comparer efficacement

Également en valeurs relatives

Petits multiples

  • Commencez par choisir deux variables numériques (avec un lien réfléchi)

  • Pensez aux dimensions qu’il est possible d’ajouter (couleur, taille, etc.)

  • Attention à la contrainte des petits multiples

  • Il faudra généralement une dimension temporelle ou catégorielle pour les utiliser

Passer de données classiques au tidy

Si vos données sont organisées de façon régulière (méthodique), il est possible d’utiliser une des fonctions :

Plus d’informations dans ce chapitre de livre consacré au tidying des données.